/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-10-16 17:08:16
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-10-17 08:15:42
 * @FilePath: /react18-vite-admin/src/components/ui/CustomChart/CustomChart.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import * as Echarts from 'echarts';
import {
    forwardRef,
    useEffect,
    type CSSProperties,
    type MutableRefObject,
    useRef
} from 'react';

import { getPercentWithPrecision } from './utils';
import type { PieItemValue } from './utils';
import { debounce } from './utils';
import './CustomChart.scoped.scss';

interface Props {
    style?: CSSProperties;
    datasetSource?: unknown[]; // 数据集 https://echarts.apache.org/zh/option.html#dataset
    extraOption?: Record<string, unknown>;
    legendShowPercent?: boolean;
}

const CustomChart = forwardRef<HTMLDivElement, Props>(
    (
        {
            style,
            datasetSource = [[]],
            extraOption = {},
            legendShowPercent = true
        },
        ref
    ) => {
        let option: Record<string, any> = {};
        let chart: Echarts.ECharts | null = null;
        const divRef = useRef<HTMLDivElement | null>(null);

        const isPieItemValue = (arg: unknown): arg is PieItemValue => {
            const asPieItemValue = arg as PieItemValue;
            if (
                typeof asPieItemValue.name === 'string' &&
                typeof asPieItemValue.value === 'number'
            ) {
                return true;
            }
            return false;
        };

        // 合并选项
        const assembleOption = () => {
            // option =
            //     merge(option, toRaw(extraOption.value), {
            //         dataset: { source: toRaw(datasetSource.value) }
            //     }) || {};
            option = extraOption;
            option.dataset = { source: datasetSource };
            if (legendShowPercent) {
                const formatter = (name: string) => {
                    const index = datasetSource.findIndex((item) => {
                        if (isPieItemValue(item)) {
                            return item.name === name;
                        }
                        throw new Error(
                            'legendShowPercent设为true，则datasetSource必须传{ name: string; value: number }的格式'
                        );
                    });
                    const percent = getPercentWithPrecision(
                        (datasetSource as PieItemValue[]).map(
                            (item) => item.value
                        ),
                        index,
                        2
                    );
                    return `${name} ${percent}%`;
                };
                if (option.legend === undefined) {
                    option.legend = { formatter };
                } else {
                    option.legend.formatter = formatter;
                }
                // option = merge(option, { legend: { formatter } }) || {};
            }
        };
        // 数据更新
        const updateChartView = debounce(() => {
            if (!chart) return;
            assembleOption();
            chart.setOption(option, true);
        }, 1000);

        // 当窗口缩放时，echart动态调整自身大小 (窗口缩放)
        const handleWindowResize = () => {
            if (!chart) return;
            chart.resize();
        };

        useEffect(() => {
            updateChartView();
        }, [datasetSource, extraOption]);

        useEffect(() => {
            ref = ref ?? divRef;
            chart = Echarts.init(
                (ref as MutableRefObject<HTMLDivElement>).current
            ); // 初始化Echart实例
            // debugger;
            updateChartView(); // 图表数据有更新
            window.addEventListener('resize', handleWindowResize); // 窗口大小变化
            return () => {
                window.removeEventListener('resize', handleWindowResize);
            };
        }, []);

        return (
            <div className="chart" ref={divRef} style={style}>
                暂无数据
            </div>
        );
    }
);

export default CustomChart;
